﻿#ifndef CLOUDLINKER_RESPONSE_UTILS_H
#define CLOUDLINKER_RESPONSE_UTILS_H

#include <Poco/Net/HTTPServerResponse.h>
#include <Poco/Net/HTTPCookie.h>
#include <Poco/Net/NameValueCollection.h>
#include <Poco/JSON/JSON.h>
#include <Poco/JSON/Object.h>
#include <Poco/JSON/Array.h>
#include <Poco/File.h>
#include <Poco/FileStream.h>
#include <Poco/Path.h>
#include <Poco/DateTime.h>
#include <Poco/DateTimeFormat.h>
#include <Poco/DateTimeFormatter.h>
#include <Poco/DateTimeParser.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/StreamCopier.h>
#include <Poco/DeflatingStream.h>
#include <Poco/SharedPtr.h>
#include <Poco/CountingStream.h>
#include <Poco/NullStream.h>
#include <Poco/Format.h>
#include <Poco/String.h>
#include <fstream>
#include <memory>
#include <vector>
#include <map>
#include "../CLink_Export.h"

/**
 * @namespace HttpResponseUtils
 * @brief 提供HTTP响应处理的工具函数和常量
 *
 * 该命名空间包含用于处理HTTP响应的各种工具函数和常量，
 * 包括状态码、内容类型、响应头设置、响应发送等功能。
 */
namespace CLink
{
namespace HttpResponseUtils
{

/**
 * @namespace Status
 * @brief HTTP状态码常量
 *
 * 包含标准HTTP状态码的常量定义，基于Poco::Net::HTTPResponse。
 */
namespace Status
{
    using Poco::Net::HTTPResponse;
    /** @brief 继续处理请求 (100) */
    const int CONTINUE = HTTPResponse::HTTP_CONTINUE;
    /** @brief 请求成功 (200) */
    const int OK = HTTPResponse::HTTP_OK;
    /** @brief 资源创建成功 (201) */
    const int CREATED = HTTPResponse::HTTP_CREATED;
    /** @brief 请求已接受但尚未处理完成 (202) */
    const int ACCEPTED = HTTPResponse::HTTP_ACCEPTED;
    /** @brief 请求成功但无返回内容 (204) */
    const int NO_CONTENT = HTTPResponse::HTTP_NO_CONTENT;
    /** @brief 重置内容 (205) */
    const int RESET_CONTENT = HTTPResponse::HTTP_RESET_CONTENT;
    /** @brief 部分内容 (206) */
    const int PARTIAL_CONTENT = HTTPResponse::HTTP_PARTIAL_CONTENT;
    /** @brief 永久重定向 (301) */
    const int MOVED_PERMANENTLY = HTTPResponse::HTTP_MOVED_PERMANENTLY;
    /** @brief 临时重定向 (302) */
    const int FOUND = HTTPResponse::HTTP_FOUND;
    /** @brief 查看其他位置 (303) */
    const int SEE_OTHER = HTTPResponse::HTTP_SEE_OTHER;
    /** @brief 资源未修改 (304) */
    const int NOT_MODIFIED = HTTPResponse::HTTP_NOT_MODIFIED;
    /** @brief 临时重定向，保持请求方法不变 (307) */
    const int TEMPORARY_REDIRECT = HTTPResponse::HTTP_TEMPORARY_REDIRECT;
    /** @brief 请求格式错误 (400) */
    const int BAD_REQUEST = HTTPResponse::HTTP_BAD_REQUEST;
    /** @brief 未授权 (401) */
    const int UNAUTHORIZED = HTTPResponse::HTTP_UNAUTHORIZED;
    /** @brief 禁止访问 (403) */
    const int FORBIDDEN = HTTPResponse::HTTP_FORBIDDEN;
    /** @brief 资源未找到 (404) */
    const int NOT_FOUND = HTTPResponse::HTTP_NOT_FOUND;
    /** @brief 请求方法不允许 (405) */
    const int METHOD_NOT_ALLOWED = HTTPResponse::HTTP_METHOD_NOT_ALLOWED;
    /** @brief 请求超时 (408) */
    const int REQUEST_TIMEOUT = HTTPResponse::HTTP_REQUEST_TIMEOUT;
    /** @brief 资源冲突 (409) */
    const int CONFLICT = HTTPResponse::HTTP_CONFLICT;
    /** @brief 请求体过大 (413) */
    const int PAYLOAD_TOO_LARGE = HTTPResponse::HTTP_REQUEST_ENTITY_TOO_LARGE;
    /** @brief 不支持的媒体类型 (415) */
    const int UNSUPPORTED_MEDIA_TYPE = HTTPResponse::HTTP_UNSUPPORTED_MEDIA_TYPE;
    /** @brief 预期失败 (417) */
    const int EXPECTATION_FAILED = HTTPResponse::HTTP_EXPECTATION_FAILED;
    /** @brief 请求过于频繁 (429) */
    const int TOO_MANY_REQUESTS = HTTPResponse::HTTP_TOO_MANY_REQUESTS;
    /** @brief 服务器内部错误 (500) */
    const int INTERNAL_SERVER_ERROR = HTTPResponse::HTTP_INTERNAL_SERVER_ERROR;
    /** @brief 功能未实现 (501) */
    const int NOT_IMPLEMENTED = HTTPResponse::HTTP_NOT_IMPLEMENTED;
    /** @brief 网关错误 (502) */
    const int BAD_GATEWAY = HTTPResponse::HTTP_BAD_GATEWAY;
    /** @brief 服务暂时不可用 (503) */
    const int SERVICE_UNAVAILABLE = HTTPResponse::HTTP_SERVICE_UNAVAILABLE;
    /** @brief 网关超时 (504) */
    const int GATEWAY_TIMEOUT = HTTPResponse::HTTP_GATEWAY_TIMEOUT;
    /** @brief 不支持的HTTP版本 (505) */
    const int VERSION_NOT_SUPPORTED = HTTPResponse::HTTP_VERSION_NOT_SUPPORTED;
    /** @brief 请求的范围无法满足 (416) */
    const int RANGE_NOT_SATISFIABLE = HTTPResponse::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE;
}

/**
 * @namespace ContentType
 * @brief HTTP内容类型常量
 *
 * 包含常用的MIME类型常量定义，用于设置HTTP响应的Content-Type头。
 */
namespace ContentType
{
    /** @brief 纯文本 (text/plain) */
    const std::string TEXT_PLAIN = "text/plain";
    /** @brief HTML文档 (text/html) */
    const std::string TEXT_HTML = "text/html";
    /** @brief XML文档 (text/xml) */
    const std::string TEXT_XML = "text/xml";
    /** @brief CSV数据 (text/csv) */
    const std::string TEXT_CSV = "text/csv";
    /** @brief CSS样式表 (text/css) */
    const std::string TEXT_CSS = "text/css";
    /** @brief JavaScript代码 (text/javascript) */
    const std::string TEXT_JAVASCRIPT = "text/javascript";
    /** @brief JSON数据 (application/json) */
    const std::string APPLICATION_JSON = "application/json";
    /** @brief XML应用数据 (application/xml) */
    const std::string APPLICATION_XML = "application/xml";
    /** @brief JavaScript应用 (application/javascript) */
    const std::string APPLICATION_JAVASCRIPT = "application/javascript";
    /** @brief 二进制数据流 (application/octet-stream) */
    const std::string APPLICATION_OCTET_STREAM = "application/octet-stream";
    /** @brief PDF文档 (application/pdf) */
    const std::string APPLICATION_PDF = "application/pdf";
    /** @brief ZIP压缩文件 (application/zip) */
    const std::string APPLICATION_ZIP = "application/zip";
    /** @brief URL编码表单数据 (application/x-www-form-urlencoded) */
    const std::string APPLICATION_FORM = "application/x-www-form-urlencoded";
    /** @brief 多部分表单数据 (multipart/form-data) */
    const std::string MULTIPART_FORM = "multipart/form-data";
    /** @brief PNG图像 (image/png) */
    const std::string IMAGE_PNG = "image/png";
    /** @brief JPEG图像 (image/jpeg) */
    const std::string IMAGE_JPEG = "image/jpeg";
    /** @brief GIF图像 (image/gif) */
    const std::string IMAGE_GIF = "image/gif";
    /** @brief SVG矢量图像 (image/svg+xml) */
    const std::string IMAGE_SVG = "image/svg+xml";
    /** @brief WOFF字体 (font/woff) */
    const std::string FONT_WOFF = "font/woff";
    /** @brief WOFF2字体 (font/woff2) */
    const std::string FONT_WOFF2 = "font/woff2";
}

/**
 * @namespace Charset
 * @brief HTTP字符集常量
 *
 * 包含常用的字符集常量定义，用于设置HTTP响应的Content-Type头的charset部分。
 */
namespace Charset
{
    /** @brief UTF-8字符编码 - 支持所有Unicode字符的可变长度编码，是Web开发中最常用的字符编码 */
    const std::string UTF8 = "charset=UTF-8";
}

/**
 * @namespace ContentEncoding
 * @brief HTTP内容编码类型常量
 *
 * 包含标准的HTTP内容编码类型常量定义，用于设置HTTP响应的Content-Encoding头。
 */
namespace ContentEncoding
{
    /** @brief GZIP压缩编码 - 使用GZIP算法压缩的内容 */
    const std::string GZIP = "gzip";
    /** @brief DEFLATE压缩编码 - 使用DEFLATE算法压缩的内容 */
    const std::string DEFLATE = "deflate";
    /** @brief Brotli压缩编码 - 使用Brotli算法压缩的内容，通常比GZIP更高效 */
    const std::string BR = "br";
    /** @brief COMPRESS压缩编码 - 使用UNIX compress程序压缩的内容，较旧的压缩方式 */
    const std::string COMPRESS = "compress";
    /** @brief 无编码 - 表示内容未经过任何编码处理 */
    const std::string IDENTITY = "identity";
}

/**
 * @namespace PseudoHeaders
 * @brief HTTP/2伪头部字段常量
 *
 * 包含HTTP/2协议中使用的伪头部字段常量定义，这些字段以冒号开头。
 */
namespace PseudoHeaders
{
    /** @brief HTTP/2权限伪头部 - 指定请求的主机和端口信息，相当于HTTP/1.x的Host头部 */
    const std::string AUTHORITY = ":authority";
    /** @brief HTTP/2请求方法伪头部 - 指定HTTP请求方法（如GET、POST等） */
    const std::string METHOD = ":method";
    /** @brief HTTP/2路径伪头部 - 指定请求的资源路径，包括查询参数 */
    const std::string PATH = ":path";
    /** @brief HTTP/2协议方案伪头部 - 指定使用的协议（如http、https） */
    const std::string SCHEME = ":scheme";
    /** @brief HTTP/2状态伪头部 - 指定响应的状态码，相当于HTTP/1.x的状态行 */
    const std::string STATUS = ":status";
}

/**
 * @struct ErrorDetail
 * @brief 错误详细信息结构
 *
 * 用于表示API错误响应中的详细错误信息，包含错误代码、消息和相关字段。
 */
struct CLINK_CLASS ErrorDetail
{
    int code;            ///< 错误代码
    std::string message; ///< 错误消息
    std::string field;   ///< 相关字段名称（可选）
};

/**
 * @typedef Headers
 * @brief HTTP头部集合类型
 *
 * 使用Poco::Net::NameValueCollection表示HTTP头部的键值对集合。
 */
using Headers = Poco::Net::NameValueCollection;

/**
 * @typedef Cookies
 * @brief HTTP Cookie集合类型
 *
 * 使用std::vector存储Poco::Net::HTTPCookie对象的集合。
 */
using Cookies = std::vector<Poco::Net::HTTPCookie>;

/**
 * @typedef LinkItems
 * @brief HTTP Link头部项集合类型
 *
 * 使用std::map存储Link头部的URL和关系类型的键值对。
 */
using LinkItems = std::map<std::string, std::string>;

/**
 * @brief 设置HTTP响应状态码
 *
 * @param response HTTP服务器响应对象
 * @param statusCode HTTP状态码，建议使用Status命名空间中定义的常量
 */
CLINK_FUNCTION inline void setStatus(Poco::Net::HTTPServerResponse &response, int statusCode)
{
    response.setStatus(static_cast<Poco::Net::HTTPServerResponse::HTTPStatus>(statusCode));
}

/**
 * @brief 设置HTTP协议版本
 *
 * @param response HTTP服务器响应对象
 * @param version HTTP版本字符串，如"HTTP/1.1"或"HTTP/2"
 */
CLINK_FUNCTION inline void setHttpVersion(Poco::Net::HTTPServerResponse &response, const std::string &version)
{
    response.setVersion(version);
}

/**
 * @brief 设置HTTP/2伪头部字段
 *
 * @param response HTTP服务器响应对象
 * @param pseudoHeader 伪头部字段名称，建议使用PseudoHeaders命名空间中定义的常量
 * @param value 伪头部字段值
 */
CLINK_FUNCTION inline void setPseudoHeader(Poco::Net::HTTPServerResponse &response,
                            const std::string &pseudoHeader, const std::string &value)
{
    response.set(pseudoHeader, value);
}

/**
 * @brief 设置响应的Content-Type头部和字符集
 *
 * @param response HTTP服务器响应对象
 * @param contentType 内容类型，建议使用ContentType命名空间中定义的常量
 * @param charset 字符集，建议使用Charset命名空间中定义的常量，默认为空
 */
CLINK_FUNCTION inline void setContentType(Poco::Net::HTTPServerResponse &response,
                            const std::string &contentType,
                            const std::string &charset = CLink::HttpResponseUtils::Charset::UTF8)
{
    std::string fullType = contentType;
    if (!charset.empty())
    {
        fullType += "; " + charset;
    }
    response.setContentType(fullType);
}

/**
 * @brief 设置响应的Content-Encoding头部
 *
 * @param response HTTP服务器响应对象
 * @param encoding 内容编码类型，建议使用ContentEncoding命名空间中定义的常量
 */
CLINK_FUNCTION inline void setContentEncoding(Poco::Net::HTTPServerResponse &response,
                                const std::string &encoding)
{
    response.set("Content-Encoding", encoding);
}

/**
 * @brief 设置响应的Content-Language头部
 *
 * @param response HTTP服务器响应对象
 * @param language 语言标识符，如"en-US"、"zh-CN"等
 */
CLINK_FUNCTION inline void setContentLanguage(Poco::Net::HTTPServerResponse &response,
                                const std::string &language)
{
    response.set("Content-Language", language);
}

/**
 * @brief 设置单个HTTP响应头
 *
 * @param response HTTP服务器响应对象
 * @param name 头部字段名称
 * @param value 头部字段值
 */
CLINK_FUNCTION inline void setHeader(Poco::Net::HTTPServerResponse &response,
                        const std::string &name, const std::string &value)
{
    response.set(name, value);
}

/**
 * @brief 批量设置多个HTTP响应头
 *
 * @param response HTTP服务器响应对象
 * @param headers 头部字段集合，键值对形式
 */
CLINK_FUNCTION inline void setHeaders(Poco::Net::HTTPServerResponse &response,
                        const Headers &headers)
{
    for (const auto &header : headers)
    {
        response.set(header.first, header.second);
    }
}

/**
 * @brief 设置内容安全策略(CSP)头部
 *
 * 内容安全策略(CSP)是一种安全机制，用于防止跨站脚本攻击(XSS)等安全问题。
 *
 * @param response HTTP服务器响应对象
 * @param policy CSP策略字符串，如"default-src 'self'"
 */
CLINK_FUNCTION inline void setContentSecurityPolicy(Poco::Net::HTTPServerResponse &response,
                                        const std::string &policy)
{
    response.set("Content-Security-Policy", policy);
}

/**
 * @brief 设置Cache-Control头部
 *
 * @param response HTTP服务器响应对象
 * @param maxAgeSeconds 最大缓存时间(秒)，默认3600秒(1小时)
 * @param isPublic 是否为公共缓存，默认为true
 * @param mustRevalidate 是否必须重新验证，默认为false
 */
CLINK_FUNCTION inline void setCacheControl(Poco::Net::HTTPServerResponse &response,
                            int maxAgeSeconds = 3600,
                            bool isPublic = true,
                            bool mustRevalidate = false)
{
    std::string cacheControl = isPublic ? "public" : "private";
    cacheControl += ", max-age=" + std::to_string(maxAgeSeconds);
    if (mustRevalidate)
    {
        cacheControl += ", must-revalidate";
    }
    response.set("Cache-Control", cacheControl);
}

/**
 * @brief 设置响应为不可缓存
 *
 * 设置多个头部字段，确保响应不会被任何缓存机制缓存。
 *
 * @param response HTTP服务器响应对象
 */
CLINK_FUNCTION inline void setNoCache(Poco::Net::HTTPServerResponse &response)
{
    response.set("Cache-Control", "no-store, no-cache, must-revalidate");
    response.set("Pragma", "no-cache");
    response.set("Expires", "0");
}

/**
 * @brief 设置ETag头部
 *
 * ETag(实体标签)是资源的特定版本的标识符，用于缓存验证。
 *
 * @param response HTTP服务器响应对象
 * @param etag 实体标签值，通常是资源内容的哈希值
 */
CLINK_FUNCTION inline void setETag(Poco::Net::HTTPServerResponse &response, const std::string &etag)
{
    response.set("ETag", etag);
}

/**
 * @brief 设置Last-Modified头部
 *
 * 指示资源的最后修改时间，用于缓存验证。
 *
 * @param response HTTP服务器响应对象
 * @param timestamp 资源的最后修改时间戳
 */
CLINK_FUNCTION inline void setLastModified(Poco::Net::HTTPServerResponse &response,
                            const Poco::Timestamp &timestamp)
{
    response.set("Last-Modified", Poco::DateTimeFormatter::format(
                                        Poco::DateTime(timestamp), Poco::DateTimeFormat::HTTP_FORMAT));
}

/**
 * @brief 设置Retry-After头部
 *
 * 指示客户端在指定的秒数后再次尝试请求，通常用于限流或服务暂时不可用的情况。
 *
 * @param response HTTP服务器响应对象
 * @param seconds 客户端应等待的秒数
 */
CLINK_FUNCTION inline void setRetryAfter(Poco::Net::HTTPServerResponse &response,
                            int seconds)
{
    response.set("Retry-After", std::to_string(seconds));
}

/**
 * @brief 设置Vary头部
 *
 * 指示哪些请求头字段用于内容协商，影响缓存行为。
 *
 * @param response HTTP服务器响应对象
 * @param varyFields 用于内容协商的请求头字段，如"Accept, Accept-Encoding"
 */
CLINK_FUNCTION inline void setVary(Poco::Net::HTTPServerResponse &response,
                    const std::string &varyFields)
{
    response.set("Vary", varyFields);
}

/**
 * @brief 添加单个HTTP Cookie
 *
 * @param response HTTP服务器响应对象
 * @param cookie Poco::Net::HTTPCookie对象
 */
CLINK_FUNCTION inline void addCookie(Poco::Net::HTTPServerResponse &response,
                        const Poco::Net::HTTPCookie &cookie)
{
    response.addCookie(cookie);
}

/**
 * @brief 添加单个HTTP Cookie（便捷方法）
 *
 * 创建并添加一个带有指定属性的Cookie。
 *
 * @param response HTTP服务器响应对象
 * @param name Cookie名称
 * @param value Cookie值
 * @param maxAgeSeconds Cookie生存时间(秒)，默认86400秒(1天)
 * @param path Cookie路径，默认为"/"
 * @param domain Cookie域，默认为空（当前域）
 * @param secure 是否仅通过HTTPS发送，默认为false
 * @param httpOnly 是否禁止JavaScript访问，默认为false
 * @param sameSite SameSite属性值（None/Lax/Strict），默认为空
 */
CLINK_FUNCTION inline void addCookie(Poco::Net::HTTPServerResponse &response,
                        const std::string &name, const std::string &value,
                        int maxAgeSeconds = 86400,
                        const std::string &path = "/",
                        const std::string &domain = "",
                        bool secure = false,
                        bool httpOnly = false,
                        const std::string &sameSite = "")
{
    Poco::Net::HTTPCookie cookie(name, value);
    cookie.setPath(path);
    if (!domain.empty())
        cookie.setDomain(domain);
    cookie.setMaxAge(maxAgeSeconds);
    cookie.setSecure(secure);
    cookie.setHttpOnly(httpOnly);
    if (!sameSite.empty())
    {
        Poco::Net::HTTPCookie::SameSite sameSiteEnum = Poco::Net::HTTPCookie::SAME_SITE_LAX;
        if (Poco::icompare(sameSite, "None") == 0)
        {
            sameSiteEnum = Poco::Net::HTTPCookie::SAME_SITE_NONE;
        }
        else if (Poco::icompare(sameSite, "Strict") == 0)
        {
            sameSiteEnum = Poco::Net::HTTPCookie::SAME_SITE_STRICT;
        }
        cookie.setSameSite(sameSiteEnum);
    }
    addCookie(response, cookie);
}

/**
 * @brief 删除HTTP Cookie
 *
 * 通过设置空值和0过期时间来删除指定的Cookie。
 *
 * @param response HTTP服务器响应对象
 * @param name 要删除的Cookie名称
 * @param path Cookie路径，默认为"/"
 * @param domain Cookie域，默认为空（当前域）
 */
CLINK_FUNCTION inline void removeCookie(Poco::Net::HTTPServerResponse &response,
                            const std::string &name,
                            const std::string &path = "/",
                            const std::string &domain = "")
{
    Poco::Net::HTTPCookie cookie(name, "");
    cookie.setPath(path);
    if (!domain.empty())
        cookie.setDomain(domain);
    cookie.setMaxAge(0); // 立即过期
    addCookie(response, cookie);
}

/**
 * @brief 添加HTTP Link头部
 *
 * 根据RFC 5988规范添加Link头部，用于资源预加载、关系指示等。
 *
 * @param response HTTP服务器响应对象
 * @param url 链接的URL
 * @param rel 关系类型，如"preload"、"next"、"prev"等
 * @param type 可选的媒体类型
 */
CLINK_FUNCTION inline void addLinkHeader(Poco::Net::HTTPServerResponse &response,
                            const std::string &url,
                            const std::string &rel,
                            const std::string &type = "")
{
    std::string link = "<" + url + ">; rel=\"" + rel + "\"";
    if (!type.empty())
    {
        link += "; type=\"" + type + "\"";
    }
    response.add("Link", link);
}

/**
 * @brief 批量添加多个HTTP Link头部
 *
 * @param response HTTP服务器响应对象
 * @param links 链接项集合，键为URL，值为关系类型
 */
CLINK_FUNCTION inline void addLinkHeaders(Poco::Net::HTTPServerResponse &response,
                            const LinkItems &links)
{
    for (const auto &link : links)
    {
        addLinkHeader(response, link.first, link.second);
    }
}

/**
 * @brief 设置HTTP严格传输安全(HSTS)头部
 *
 * HSTS通知浏览器只能通过HTTPS访问该站点，提高安全性。
 *
 * @param response HTTP服务器响应对象
 * @param maxAgeSeconds 策略有效期(秒)，默认31536000秒(1年)
 * @param includeSubDomains 是否包含子域，默认为false
 */
CLINK_FUNCTION inline void setHSTS(Poco::Net::HTTPServerResponse &response,
                    int maxAgeSeconds = 31536000,
                    bool includeSubDomains = false)
{
    std::string hsts = "max-age=" + std::to_string(maxAgeSeconds);
    if (includeSubDomains)
    {
        hsts += "; includeSubDomains";
    }
    response.set("Strict-Transport-Security", hsts);
}

/**
 * @brief 设置跨域资源共享(CORS)头部
 *
 * 配置CORS策略，允许跨域请求访问资源。
 *
 * @param response HTTP服务器响应对象
 * @param allowOrigin 允许的源，默认为"*"表示允许所有源
 * @param allowMethods 允许的HTTP方法，默认为"GET, POST, PUT, DELETE, OPTIONS"
 * @param allowHeaders 允许的请求头，默认为"Content-Type, Authorization, X-Requested-With"
 * @param exposeHeaders 允许客户端访问的响应头，默认为空
 * @param maxAgeSeconds 预检请求结果缓存时间(秒)，默认86400秒(1天)
 */
CLINK_FUNCTION inline void setCORS(Poco::Net::HTTPServerResponse &response,
                    const std::string &allowOrigin = "*",
                    const std::string &allowMethods = "GET, POST, PUT, DELETE, OPTIONS",
                    const std::string &allowHeaders = "Content-Type, Authorization, X-Requested-With",
                    const std::string &exposeHeaders = "",
                    int maxAgeSeconds = 86400)
{
    response.set("Access-Control-Allow-Origin", allowOrigin);
    response.set("Access-Control-Allow-Methods", allowMethods);
    response.set("Access-Control-Allow-Headers", allowHeaders);
    response.set("Access-Control-Max-Age", std::to_string(maxAgeSeconds));

    if (!exposeHeaders.empty())
    {
        response.set("Access-Control-Expose-Headers", exposeHeaders);
    }
}

/**
 * @brief 发送HTTP响应的通用方法
 *
 * 使用模板函数处理不同类型的响应内容生成器。
 *
 * @tparam ContentGenerator 内容生成器类型
 * @param response HTTP服务器响应对象
 * @param statusCode HTTP状态码
 * @param contentType 响应内容类型
 * @param generator 内容生成器函数或对象
 * @param compress 是否启用压缩，默认为false
 * @param encoding 压缩编码方式，默认为GZIP
 */
template <typename ContentGenerator>
CLINK_FUNCTION void sendResponse(Poco::Net::HTTPServerResponse &response,
                    int statusCode,
                    const std::string &contentType,
                    ContentGenerator generator,
                    bool compress = false,
                    const std::string &encoding = ContentEncoding::GZIP);

/**
 * @brief 发送文本响应
 *
 * 发送纯文本格式的HTTP响应。
 *
 * @param response HTTP服务器响应对象
 * @param text 要发送的文本内容
 * @param statusCode HTTP状态码，默认为200 OK
 * @param contentType 内容类型，默认为text/plain
 * @param compress 是否启用压缩，默认为false
 */
CLINK_FUNCTION void sendText(Poco::Net::HTTPServerResponse &response,
                const std::string &text,
                int statusCode = Status::OK,
                const std::string &contentType = ContentType::TEXT_PLAIN,
                bool compress = false);

/**
 * @brief 发送HTML响应
 *
 * 发送HTML格式的HTTP响应。
 *
 * @param response HTTP服务器响应对象
 * @param html 要发送的HTML内容
 * @param statusCode HTTP状态码，默认为200 OK
 * @param compress 是否启用压缩，默认为false
 */
CLINK_FUNCTION void sendHtml(Poco::Net::HTTPServerResponse &response,
                const std::string &html,
                int statusCode = Status::OK,
                bool compress = false);

/**
 * @brief 发送JSON响应
 *
 * 发送JSON格式的HTTP响应。
 *
 * @param response HTTP服务器响应对象
 * @param json Poco::JSON::Object对象
 * @param statusCode HTTP状态码，默认为200 OK
 * @param compress 是否启用压缩，默认为false
 */
CLINK_FUNCTION void sendJson(Poco::Net::HTTPServerResponse &response,
                const Poco::JSON::Object &json,
                int statusCode = Status::OK,
                bool compress = false);

/**
 * @brief 发送JSON数组响应
 *
 * 发送Poco::JSON::Array对象作为HTTP响应。
 *
 * @param response HTTP服务器响应对象
 * @param jsonArray Poco::JSON::Array对象
 * @param statusCode HTTP状态码，默认为200 OK
 * @param compress 是否启用压缩，默认为false
 */
CLINK_FUNCTION void sendJsonArray(Poco::Net::HTTPServerResponse &response,
                    const Poco::JSON::Array &jsonArray,
                    int statusCode = Status::OK,
                    bool compress = false);

/**
 * @brief 发送错误信息（JSON格式）
 *
 * 发送包含错误代码、消息和详细信息的JSON格式错误响应。
 *
 * @param response HTTP服务器响应对象
 * @param statusCode HTTP错误状态码
 * @param errorCode 错误代码字符串，用于客户端识别错误类型
 * @param message 错误消息
 * @param details 详细错误信息数组，默认为空
 */
CLINK_FUNCTION void sendErrorJson(Poco::Net::HTTPServerResponse &response,
                    int statusCode,
                    const std::string &errorCode,
                    const std::string &message,
                    const std::vector<ErrorDetail> &details = {});

/**
 * @brief 发送文件响应
 *
 * 读取并发送文件内容作为HTTP响应，支持部分内容请求和内容协商。
 *
 * @param response HTTP服务器响应对象
 * @param filePath 要发送的文件路径
 * @param attachmentName 附件名称，如果不为空，将添加Content-Disposition头部
 * @param additionalHeaders 要添加的额外头部
 * @param rangeHeader Range请求头的值，用于支持部分内容请求
 * @param compress 是否启用压缩，默认为false
 */
CLINK_FUNCTION void sendFile(Poco::Net::HTTPServerResponse &response,
                const std::string &filePath,
                const std::string &attachmentName = "",
                const Headers &additionalHeaders = Headers(),
                const std::string &rangeHeader = "",
                bool compress = false);

/**
 * @brief 发送重定向响应
 *
 * 发送HTTP重定向响应，将客户端重定向到指定位置。
 *
 * @param response HTTP服务器响应对象
 * @param location 重定向目标URL
 * @param permanent 是否为永久重定向，默认为false（临时重定向）
 * @param seeOther 是否使用303 See Other状态码，默认为false
 */
CLINK_FUNCTION void redirect(Poco::Net::HTTPServerResponse &response,
                const std::string &location,
                bool permanent = false,
                bool seeOther = false);

/**
 * @brief 发送204 No Content响应
 *
 * 发送不包含响应体的204 No Content状态码响应。
 *
 * @param response HTTP服务器响应对象
 * @param headers 要添加的额外头部，默认为空
 */
CLINK_FUNCTION void sendNoContent(Poco::Net::HTTPServerResponse &response,
                    const Headers &headers = Headers());

/**
 * @brief 发送二进制数据响应
 *
 * 发送原始二进制数据作为HTTP响应。
 *
 * @param response HTTP服务器响应对象
 * @param data 指向二进制数据的指针
 * @param length 数据长度（字节）
 * @param contentType 内容类型，默认为application/octet-stream
 * @param statusCode HTTP状态码，默认为200 OK
 * @param compress 是否启用压缩，默认为false
 */
CLINK_FUNCTION void sendBinary(Poco::Net::HTTPServerResponse &response,
                const char *data,
                size_t length,
                const std::string &contentType = ContentType::APPLICATION_OCTET_STREAM,
                int statusCode = Status::OK,
                bool compress = false);

/**
 * @brief 设置内容分发网络(CDN)相关头部
 *
 * 添加CDN特定的头部信息，用于跟踪和调试CDN缓存。
 *
 * @param response HTTP服务器响应对象
 * @param cacheId CDN缓存标识符
 * @param edgeTraceId CDN边缘节点跟踪标识符
 */
CLINK_FUNCTION void setCDNHeaders(Poco::Net::HTTPServerResponse &response,
                    const std::string &cacheId,
                    const std::string &edgeTraceId);

/**
 * @brief 设置速率限制相关头部
 *
 * 添加速率限制信息的头部，用于API限流。
 *
 * @param response HTTP服务器响应对象
 * @param limit 时间窗口内允许的最大请求数
 * @param remaining 当前时间窗口内剩余的请求数
 * @param resetTime 速率限制重置的时间戳（Unix时间戳）
 */
CLINK_FUNCTION void setRateLimitHeaders(Poco::Net::HTTPServerResponse &response,
                            int limit,
                            int remaining,
                            int resetTime);

/**
 * @brief 获取文件的MIME类型
 *
 * 根据文件扩展名确定适当的MIME类型。
 *
 * @param filePath 文件路径
 * @return std::string 文件的MIME类型
 */
CLINK_FUNCTION std::string getMimeType(const std::string &filePath);

/**
 * @brief 计算文件的ETag值
 *
 * 基于文件大小和修改时间生成ETag值，用于缓存验证。
 *
 * @param filePath 文件路径
 * @param fileSize 文件大小（字节）
 * @param modified 文件的最后修改时间
 * @return std::string 生成的ETag值
 */
CLINK_FUNCTION std::string computeETag(const std::string &filePath, off_t fileSize, const Poco::Timestamp &modified);

/**
 * @brief 解析HTTP日期字符串
 *
 * 将HTTP日期格式的字符串转换为Poco::Timestamp对象。
 * 支持RFC 822、RFC 850和asctime格式的日期字符串。
 *
 * @param httpDate HTTP日期格式的字符串
 * @return Poco::Timestamp 解析后的时间戳
 */
CLINK_FUNCTION Poco::Timestamp parseHttpDate(const std::string &httpDate);

/**
 * @brief 发送文件内容
 *
 * 读取并将文件内容写入指定的输出流。
 *
 * @param filePath 要发送的文件路径
 * @param out 输出流对象
 */
CLINK_FUNCTION void sendFileContent(const std::string &filePath, std::ostream &out);

/**
 * @brief 处理HTTP范围请求
 *
 * 处理部分内容请求，支持HTTP Range头部，发送文件的指定部分。
 *
 * @param response HTTP服务器响应对象
 * @param filePath 要发送的文件路径
 * @param fileSize 文件大小（字节）
 * @param rangeHeader Range请求头的值
 */
CLINK_FUNCTION void handleRangeRequest(Poco::Net::HTTPServerResponse &response,
                        const std::string &filePath,
                        off_t fileSize,
                        const std::string &rangeHeader);

// 发送响应（通用方法）
template <typename ContentGenerator>
void sendResponse(Poco::Net::HTTPServerResponse &response,
                    int statusCode,
                    const std::string &contentType,
                    ContentGenerator generator,
                    bool compress,
                    const std::string &encoding)
{
    setStatus(response, statusCode);
    setContentType(response, contentType, Charset::UTF8);

    if (compress)
    {
        setContentEncoding(response, encoding);
        std::ostream &rawOut = response.send();
        Poco::SharedPtr<std::ostream> pOut(&rawOut);
        Poco::DeflatingOutputStream deflater(*pOut, Poco::DeflatingStreamBuf::STREAM_GZIP);
        generator(deflater);
        deflater.close();
    }
    else
    {
        std::ostream &out = response.send();
        generator(out);
    }
}

} // namespace HttpResponseUtils
} // namespace CLink
#endif // CLOUDLINKER_RESPONSE_UTILS_H